#最终版本包含上传人脸 和 识别人脸的功能
import face_recognition
import requests
from flask import Flask, jsonify, request, redirect
import time
import timeout_decorator
from flask_cors import CORS

# You can change this to any folder on your system
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

app = Flask(__name__)
CORS(app, supports_credentials=True)#配置跨域请求
url_getAllFace = 'http://220.179.32.170:8082/api/FaceDetection/GetFace'
url_getUserInfo = 'http://220.179.32.170:8082/api/FaceDetection/GetFaceIndex'
url_addFace = 'http://220.179.32.170:8082/api/FaceDetection/PostSaveFace'

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

#调用系统摄像头 识别人脸 摄像头默认看不到 、、、、（请注意 数据库中不能含有无效的encoding否则报错）
@app.route('/faceRecognition', methods=['GET', 'POST'])
def setInfo():
    try:
        return run()
    except timeout_decorator.timeout_decorator.TimeoutError: #函数超时捕获 被认定为未检测到
        result = {
            "msg":False,
            "errorMsg":"识别失败，可能是该人脸未注册，或者摄像头中未出现人脸"
        }   
        return jsonify(result)

@timeout_decorator.timeout(7,use_signals=False)#函数超时装饰器 7秒
def run():
    import cv2
    # url='http://dlhtx.zicp.vip:3000/face/getAllFace'
    r = requests.get(url_getAllFace) #发get请求
    result = r.json()['data']
    print(r.json())
    list_to_float = []
    #将数组字符串转换成数组数字 ['1','2'] => [1,2]
    for each in result:
        each_line=list(map(lambda x: float(x), each))
        list_to_float.append(each_line)
    known_face_encoding = list_to_float
    video_capture = cv2.VideoCapture(0)
    #初始化json参数
    face_found= False #是否存在人脸
    userInfo='' #用户基本信息
    process_this_frame = True 
    exitFace = ''
    while True:
        ret, frame = video_capture.read() #抓取单一针
        small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)#重新更改针大小 让他运行起来更快
        rgb_small_frame = small_frame[:, :, ::-1] #把opencv默认的bgr格式转换成rgb格式
        if process_this_frame:
            face_locations = face_recognition.face_locations(rgb_small_frame)
            face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
            #对该帧的encoding和数据库中的进行比对
            for face_encoding in face_encodings:
                    face_found = True
                    match_results = face_recognition.compare_faces(known_face_encoding, face_encoding,tolerance=0.41)
                    #如果比对存在 则使用index来查找数据库
                    if True in match_results:
                        first_match_index = match_results.index(True)
                        index = first_match_index
                        print(index)
                        # url='http://dlhtx.zicp.vip:3000/face/getUserInfo'
                        data = {'indexid':index}
                        r = requests.get(url_getUserInfo,data) #发get请求
                        print(r.json())
                        res = r.json()['result']
                        userInfo = res
                        print(res)
        process_this_frame = not process_this_frame
        for (top, right, bottom, left), name in zip(face_locations,['catcing']):
            print('绘制')
            # Scale back up face locations since the frame we detected in was scaled to 1/4 size
            top *= 4
            right *= 4
            bottom *= 4
            left *= 4
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
            cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
            font = cv2.FONT_HERSHEY_DUPLEX
            cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (200, 255, 255), 1)
        # cv2.imshow('Video ', frame)
        print('正在捕捉...')
        if cv2.waitKey(1) & 0xFF == ord('q'):   
            break  
        #对查找的用户信息进行判断 每个循环都要判断 如果找到信息则跳出循环
        if len(userInfo) != 0:
            break
    #释放画面和销毁所有cv2window
    video_capture.release()
    cv2.destroyAllWindows()
    result = {
        "msg":True,
        "result": userInfo
    }
    return jsonify(result)


#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#


#增加人脸接口 
# @app.route('/addFace', methods=['GET', 'POST'])
# def upload_image():
# #查看上传的是否是合法的图片
#     if request.method == 'POST':
#         print(request.files['file'])
#         if 'file' not in request.files:
#             return redirect(request.url)

#         file = request.files['file']
#         form = request.form #获取formdata中的参数
#         print(form.get('name'))
#         if file.filename == '':
#             return redirect(request.url)

#         if file and allowed_file(file.filename):
#             #合法的 开始判断
#             return detect_faces_in_image(file,form)

#     # If no valid image file was uploaded, show the file upload form:
#     return '''
#     <!doctype html>
#     <title>Is this a picture ?</title>
#     <h1>Upload a picture and see if it's a picture!</h1>
#     <form method="POST" enctype="multipart/form-data">
#         <input type="file" name="file">
#         <input type="submit" value="Upload">
#     </form>
#     '''


# def detect_faces_in_image(file_stream,form):
#     #获取所有人脸数据
#     # url='http://dlhtx.zicp.vip:3000/face/getAllFace'
#     r = requests.get(url_getAllFace) #发get请求
#     result = r.json()['data']
#     print(r.json())
#     list_to_float = []
#     #将数组字符串转换成数组数字
#     for each in result:
#         each_line=list(map(lambda x: float(x), each))
#         list_to_float.append(each_line)
#     known_face_encoding = list_to_float

#     # Load the uploaded image file
#     img = face_recognition.load_image_file(file_stream)
#     # print(img)
#     # Get face encodings for any faces in the uploaded image
#     unknown_face_encodings = face_recognition.face_encodings(img)

#     face_found = False
#     msg = False
#     errorMsg = ''
#     result=''
#     #将数组转化为字符串
#     if len(unknown_face_encodings) > 0:
#         unknown_face_str  = ','.join([str(x) for x in unknown_face_encodings[0]]).strip().replace(' ', '').replace("\n", ""),
#         face_found = True
#         #tolerance 为人脸识别公差 大坑！ 默认0.6非常不严谨
#         match_results = face_recognition.compare_faces(known_face_encoding, unknown_face_encodings[0],tolerance=0.41)
#         if True in match_results:
#             msg = False
#             errorMsg = '该人脸已被注册'
#         else:
#             # url='http://220.179.32.170:8082/api/FaceDetection/PostSaveFace'
#             data = {'CardID':form.get('CardID'),'encoding':unknown_face_str}
#             r = requests.post(url_addFace,data) #发get请求
#             # print(r)#返回<Response [200]>
#             print(r.json())#将返回的json串转为字典
#             if r.json()['success'] == True:
#                 msg=True
#                 result='添加成功'
#             else:
#                 msg=False
#                 result='添加失败'

#     # Return the result as json
#     result = {
#         "face_found_in_image": face_found,
#         "msg": msg,
#         'errorMsg':errorMsg,
#         'result':result
#     }
#     return jsonify(result)

#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#身份证识别接口
@app.route('/cardRecognition', methods=['GET', 'POST'])
def upload_image():
#查看上传的是否是合法的图片
    if request.method == 'POST':
        print(request.files['file'])
        if 'file' not in request.files:
            return redirect(request.url)

        file = request.files['file']
        form = request.form #获取formdata中的参数
        print(form.get('name'))
        if file.filename == '':
            return redirect(request.url)

        if file and allowed_file(file.filename):
            #合法的 开始判断
            return detect_faces_in_image(file,form)

    # If no valid image file was uploaded, show the file upload form:
    return '''
    <!doctype html>
    <title>Is this a picture ?</title>
    <h1>Upload a picture and see if it's a picture!</h1>
    <form method="POST" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit" value="Upload">
    </form>
    '''


def detect_faces_in_image(file_stream,form):
    #获取所有人脸数据
    # url='http://dlhtx.zicp.vip:3000/face/getAllFace'
    r = requests.get(url_getAllFace) #发get请求
    result = r.json()['data']
    print(r.json())
    list_to_float = []
    #将数组字符串转换成数组数字
    for each in result:
        each_line=list(map(lambda x: float(x), each))
        list_to_float.append(each_line)
    known_face_encoding = list_to_float

    # Load the uploaded image file
    img = face_recognition.load_image_file(file_stream)
    # print(img)
    # Get face encodings for any faces in the uploaded image
    unknown_face_encodings = face_recognition.face_encodings(img)

    face_found = False
    msg = False
    errorMsg = ''
    result=''
    #将数组转化为字符串
    if len(unknown_face_encodings) > 0:
        unknown_face_str  = ','.join([str(x) for x in unknown_face_encodings[0]]).strip().replace(' ', '').replace("\n", ""),
        face_found = True
        #tolerance 为人脸识别公差 大坑！ 默认0.6非常不严谨
        match_results = face_recognition.compare_faces(known_face_encoding, unknown_face_encodings[0],tolerance=0.41)
        if True in match_results:
            msg = False
            errorMsg = '该人脸已被注册'
        else:
            # url='http://220.179.32.170:8082/api/FaceDetection/PostSaveFace'
            data = {'CardID':form.get('CardID'),'encoding':unknown_face_str,'brName':form.get('brName'),'brSex':form.get('brSex')}
            r = requests.post(url_addFace,data) #发get请求
            # print(r)#返回<Response [200]>
            print(r.json())#将返回的json串转为字典
            if r.json()['success'] == True:
                msg=True
                result = r.json()
            else:
                msg=False
                result='身份证识别失败'

    # Return the result as json
    result = {
        "face_found_in_image": face_found,
        "msg": msg,
        'errorMsg':errorMsg,
        'result':result
    }
    return jsonify(result)
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#
#---------------------------------------------接口分界线----------------------------------#

#打印ｐｄｆ

# import win32print
# import win32ui
# import win32con
# import win32api
# @app.route('/printPDF', methods=['GET', 'POST'])
# def printPDF():
#     GHOSTSCRIPT_PATH = r"C:\Users\Administrator\Desktop\GHOSTSCRIPT\bin\gswin32.exe" #主要通过ghostscript来控制
#     GSPRINT_PATH =  r"C:\Users\Administrator\Desktop\GSPRINT\gsprint.exe"
#     # YOU CAN PUT HERE THE NAME OF YOUR SPECIFIC PRINTER INSTEAD OF DEFAULT
#     currentprinter = win32print.GetDefaultPrinter()
#     win32api.ShellExecute(0, 'open', GSPRINT_PATH, '-ghostscript "'+GHOSTSCRIPT_PATH+'" -dQUIET -dNOPROMPT -printer"'+currentprinter+'" "1.pdf"', '.', 0) 


#     # Return the result as json
#     result = {
#         "face_found_in_image": face_found,
#         "msg": msg,
#         'errorMsg':errorMsg,
#         'result':result
#     }
#     return jsonify(result)

# import json
# import os
# import win32com.client, pythoncom
# @app.route('/readCard', methods=['GET'])
# def readCard():
#     pythoncom.CoInitialize()
#     targetURL = r'file:///C:/Users/Administrator/Desktop/faceRecognize/face/readCard.html'
#     iewindow = win32com.client.DispatchEx('InternetExplorer.Application.1')
#     iewindow.Visible = 0
#     iewindow.Navigate(targetURL) # 打开网页
#     time.sleep(2)
#     iewindow.Quit()

#     f = open('card.txt','r',encoding="utf-8")
#     str = f.read()
#     f.close()

#     f=open('card.txt', "r+")
#     f.truncate()#清空文件
#     print(json.loads(str))
    
#     # Return the result as json
#     result = {
#         "msg": True,
#         'result':json.loads(str)
#     }
#     return jsonify(result)

# @app.route('/writeTxt', methods=['GET','POST'])
# def writeTxt():
#     if request.args.get('fail'):
#         idInfo={'readError':'读取失败'}
#     else:
#         name = request.args.get('name')
#         sex = request.args.get('sex')
#         nation =  request.args.get('nation')
#         born =  request.args.get('born')
#         address =  request.args.get('address')
#         cardNo =  request.args.get('cardNo')
#         issuedAt =  request.args.get('issuedAt')
#         effectedDate =  request.args.get('effectedDate')
#         expiredDate =  request.args.get('expiredDate')
#         pictureBase64 = request.args.get('pictureBase64')
        
#         idInfo = {
#             'name':name,
#             'sex':sex,
#             'nation':nation,
#             'born':born,
#             'address':address,
#             'cardNo':cardNo,
#             'issuedAt':issuedAt,
#             'effectedDate':effectedDate,
#             'expiredDate':expiredDate,
#             'pictureBase64':pictureBase64,
#         }
#     # idInfo = json.dumps(idInfo)
#     print(json.dumps(idInfo))
#     # txt = txt.encode('utf-8').decode()
#     with open('card.txt','w' ,encoding="utf-8") as f:
#         f.write(json.dumps(idInfo))
#     # Return the result as json
#     result = {
#         "msg": True
#     }
#     return jsonify(result)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5001, debug=True)